/*
 * IClientNetworkInterface.java
 *
 * Created on October 9, 2006, 1:25 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package net.sf.iSnake.aimodule;

import java.awt.Color;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import net.sf.iSnake.core.*;


/**
 * This handles the socket connection from client side.
 * 
 * @author Suraj
 * 
 * Changes made by TLM on Jan 25, 2007
 * 1. removed the line "import net.sf.conf.MessageProtocol;"
 * 2. changed "package net.sf.client;" to "package net.sf.iSnake.core"
 * 3. Added getter and setter for "iClientNo"
 */
public class IClientNetworkInterface extends Thread{
    private Socket Soc=null;
    private boolean stop=false;
    private int Port;
    private int iClientNo;
    private InetAddress Server;
    private ObjectInputStream ois=null;
    private ObjectOutputStream oos=null;
    private boolean preMode;
    private boolean postMode;
    private premodeISCPpacket prePacket;
    private postmodeISCPpacketForSend postSendPacket;
    private postmodeISCPpacketForMulticast postGetPacket;
    
    private AnalyseWall anz_Wall;
    private Snake iSnake;
    private AnalysePath anz_path;
    
    /**
     * Connects to the Server(localhost) at the specified port.
     * @param Port The Port number of server to the Connection is to be made.
     */
    public IClientNetworkInterface(int Port) {
        this.Port=Port;
        this.iClientNo = -1;
        //the server is at localhost
        try {
            this.Server=InetAddress.getLocalHost();
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
        }
        this.preMode=true;
        this.postMode=false;
        this.start();
    }

    public void run(){
        //Connects with the server
        try{
            Soc = new Socket(Server,Port);
            Soc.setTcpNoDelay(true);
            //Connection Established With server.
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        //opens the Object I/O stream
        try{
            oos=new ObjectOutputStream(Soc.getOutputStream());
            ois=new ObjectInputStream(Soc.getInputStream());
            //Object i/o stream is opened
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        //Receives the objects
        if(Soc.isConnected()){
            Object  obj=null;
            //reads this Client's no
            try {
                iClientNo=ois.readInt();
                this.prePacket=new premodeISCPpacket();
                this.prePacket.setPremodeCommand(ISCP.PRE_CMD_LocalPlayerPreference);
                PlayerPreferences pp=new PlayerPreferences();
                pp.setPlayer_id(iClientNo);
                pp.setSnakeColor(Color.GREEN);
                pp.setName("ImJ-iSnake");
                prePacket.setLocalPlayerPereference(pp);
                this.send(prePacket);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            try {
                while( (obj=ois.readObject()) != null && !stop) {
                    // TODO receive the objects here and process it
                    // send all the objects received to the gameController thread
                    if(this.preMode){
                        prePacket=(premodeISCPpacket)obj;
                        if(prePacket.getPremodeCommand().equals(ISCP.PRE_CMD_RemotePlayerPreference)){
                            //No need for isnake  
                            System.out.println("iSnake:Remote Player Pref received");
                        }
                        else if(prePacket.getPremodeCommand().equals(ISCP.PRE_CMD_WallCoordinate)){
                            //Analyse the wall
                            anz_Wall=new AnalyseWall(prePacket.getWallCoordinates());
                            System.out.println("iSnake: Wall Coords received and analysed.");
                        }
                        else if(prePacket.getPremodeCommand().equals(ISCP.PRE_CMD_SnakeStartCoordinate)){
                            //get snake start Coocrdinates here (keep record of isnake only)
                            iSnake=new Snake();
                            iSnake.setHead((GameAreaCoordinate)prePacket.getSnakeStartPosition().get(iClientNo));
                        }
                        else if(prePacket.getPremodeCommand().equals(ISCP.PRE_CMD_GameSpeed)){
                            //Not needed for isnake
                        }
                        else if(prePacket.getPremodeCommand().equals(ISCP.PRE_CMD_PrepareForGameStart)){
                            //Not needed for isnake
                            //now wall is comming
                        }
                        else if(prePacket.getPremodeCommand().equals(ISCP.PRE_CMD_Switch_To_PostMode)){
                            //Change the Mode
                            this.postMode=true;
                            this.preMode=false;
                            //send the sync signal here to the server
                            //this.sleep(20);
                            postSendPacket =new postmodeISCPpacketForSend(ISCP.POST_CMD_SynchronizeClient);
                            //postSendPacket.setPostmodeCommandSend(ISCP.POST_CMD_SynchronizeClient);
                            postSendPacket.setPlayer_id(new Short(""+iClientNo));
                            this.send(postSendPacket);
                            System.out.println("isnake: Sync pulse sent");
                        }
                    }
                    else if(this.postMode){
                        postGetPacket=(postmodeISCPpacketForMulticast)obj;
                        if(postGetPacket.getPostmodeMulticastCommand().equals(ISCP.POST_CMD_MULTICAST_CURRENT_FOOD)){
                            //call isnake's path analyer here with food and snake start position as argument and analyse wall
                            anz_path= new AnalysePath(anz_Wall,postGetPacket.getCurrentFood(),iSnake);
                            System.out.println("iSnake: Path analysed.");
                        }
                        else if(postGetPacket.getPostmodeMulticastCommand().equals(ISCP.POST_CMD_MULTICAST_DXDY)){
                            //call isnake's path analyer here with food and snake start position as argument and analyse wall
                            //get and send the Coordinate here
                            postSendPacket=new postmodeISCPpacketForSend();
                            postSendPacket.setPostmodeCommandSend(ISCP.POST_CMD_SEND_dxdy);
                            Short coor[]=anz_path.getdxdy();
                            postSendPacket.setDx(coor[0]);
                            postSendPacket.setDy(coor[1]);
                            this.send(postSendPacket);
                        }
                        else if(postGetPacket.getPostmodeMulticastCommand().equals(ISCP.POST_CMD_MULTICAST_FOOD_CONSUMED_BY)){
                            //call isnake's path analyer here with food and snake start position as argument and analyse wall
                            anz_path= new AnalysePath(anz_Wall,postGetPacket.getCurrentFood(),iSnake);
                            System.out.println("iSnake: Path analysed.");
                        }
                        else if(postGetPacket.getPostmodeMulticastCommand().equals(ISCP.POST_CMD_MULTICAST_CHANGE_LEVEL)){
                            //Currently not implemented
                            //this.postMode=false;
                            //this.preMode=true;
                        }
                        else if(postGetPacket.getPostmodeMulticastCommand().equals(ISCP.POST_CMD_GameStartPulse)){
                            //send the Coordinate here
                        }
                    }
                    
                }
            }
            catch(Exception ex) {
                //Server Unexpectedely Closed
                ex.printStackTrace();
            }
        }
    }
    
    /**
     *Send the Object to server.
     *@param obj The object to be send.
     */
    public void send(Object obj){
        try{
            oos.writeObject(obj);
            oos.flush();
            oos.reset();
        }
        catch(Exception e)        {
            e.printStackTrace();
        }
    }
    
    public void finalize (){
        try {Soc.close();}
        catch (IOException ex) {}
    }

    public void setStop(boolean stop) {
        this.stop = stop;
    }

}